package com.ifcar.app.fragment;

import com.ifcar.app.activity.BaseActivity;
import com.ifcar.app.fragment.NRTabFragment.TabManager.TabInfo;
import com.ifcar.app.view.MyTabWidget;

import android.content.Context;
import android.os.Bundle;
import android.os.SystemClock;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TabHost;
import android.widget.TabWidget;
import android.widget.TabHost.TabContentFactory;

import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;

public abstract class NRTabFragment extends NRFragment {
	private TabManager mTabManager;

	private TabHost mTabHost;

	private boolean mNeedSetup;

	@Override
	public void onViewCreatedNR(View view, Bundle savedInstanceState) {
		super.onViewCreatedNR(view, savedInstanceState);
		mTabHost = (TabHost) view.findViewById(android.R.id.tabhost);
	}

	@Override
	public void onStart() {
		super.onStart();
		if (mNeedSetup) {
			setup();
		}
	}

	public abstract int getContainerId();

	@Override
	public boolean dispatchKeyEvent(KeyEvent event) {
        if (!mNeedSetup) {
            TabInfo tabInfo = mTabManager.mTabs.get(mTabHost.getCurrentTabTag());
            if (tabInfo != null && tabInfo.fragment != null
                    && ((NRFragment) tabInfo.fragment).dispatchKeyEvent(event)) {
                return true;
            }
        }
		return super.dispatchKeyEvent(event);
	}
	
	public final void setup() {
		if (getView() == null) {
			mNeedSetup = true;
			return;
		}
		
		mNeedSetup = false;
		mTabHost.setup();
	    mTabManager = new TabManager(getActivity(), this, mTabHost,
	                getContainerId(), !hasOnTabChangeListener());
		TabWidget tabWidget = mTabHost.getTabWidget();
		if (tabWidget instanceof MyTabWidget) {
			((MyTabWidget) tabWidget).setTabHost(mTabHost);
		}
		initTabhost(mTabManager, mTabHost);
		prepareTabHost(mTabHost);
		if (!((BaseActivity) getActivity()).isPaused()) {
			applyTheme();
		}
	}
	
	boolean hasOnTabChangeListener() {
	    return false;
	}
	
	boolean isAllDummyView() {
	    return false;
	}
	
	void prepareTabHost(TabHost tabHost) {
	    
	}
	
    public void removeAllTabFragment() {
    	if (mTabManager == null) {
    		return;
    	}
        FragmentManager fm = getFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();

        if (removeAllTabFragmentInternal(ft)) {
            FragmentUtil.commitAndExec(fm, ft, false);
        }
    }
    
    private boolean removeAllTabFragmentInternal(FragmentTransaction ft) {
        Iterator<String> iterator = mTabManager.mTabs.keySet().iterator();
        boolean isStart = false;
        while (iterator.hasNext()) {
            String key = iterator.next();
            NRFragment fragment = (NRFragment) (mTabManager.mTabs.get(key).fragment);
            if (fragment != null) {
                isStart = true;
                if (fragment instanceof NRTabFragment) {
                    ((NRTabFragment) fragment).removeAllTabFragmentInternal(ft);
                }

                ft.remove(fragment);
            }
        }
        return isStart;
    }

	public void onTabChanged(String tabId) {

	}

	@Override
    public boolean dispatchActivityViewClick(View view) {
        TabInfo tabInfo = mTabManager.mTabs.get(mTabHost.getCurrentTabTag());
     
        if (null!=tabInfo && null!= tabInfo.fragment && ((NRFragment) tabInfo.fragment).dispatchActivityViewClick(view)) {
            return true;
        }
        return super.dispatchActivityViewClick(view);
    }

    /**
	 * 初始化 TabHost
	 * 
	 * @param tabManager
	 * @param tabHost
	 */
	protected void initTabhost(TabManager tabManager, TabHost tabHost) {

	}

	public TabManager getTabManager() {
		return mTabManager;
	}

	public TabHost getTabHost() {
		return mTabHost;
	}

	public void clearTabs() {
		TabWidget tabWidget = mTabHost.getTabWidget();
		if (tabWidget.getTabCount() <= 0) {
			return;
		}

		mTabManager.mContainer.removeAllViews();
		// 不加这句在2.3系统下报错
		mTabHost.setCurrentTab(0);

		tabWidget.removeAllViews();
		mTabHost.clearAllTabs();

		mTabManager.mTabs.clear();
	}

	@Override
	public void onTabSelected(boolean first) {
		super.onTabSelected(first);
		if (!first) {
			// 当first为true为在onTabChanged里调用tab中的fragment.selectInTab()
			NRFragment fragment = (NRFragment) getFragmentManager()
					.findFragmentByTag(mTabHost.getCurrentTabTag());
			if (fragment != null) {
				fragment.selectInTab();
			}
		}
	}

	@Override
	public void onTabUnSelected() {
		super.onTabUnSelected();
		NRFragment fragment = (NRFragment) getFragmentManager()
				.findFragmentByTag(mTabHost.getCurrentTabTag());
		if (fragment != null) {
			fragment.unSelectInTab();
		}
	}	

    /**
     * 此方法是对增加fragment方便调用
     */
    public Fragment addFragmentByTag(int container, Class clazz, String tag, Bundle argument) {
        return ((BaseActivity) getActivity()).addFragmentByTag(container, clazz, tag, argument);
    }

	@Override
	public void applyTheme() {
		// 如果tabwidget为空说明还没有调用tabhost的setup方法
		if (mTabHost.getTabWidget() == null) {
			return;
		}
		super.applyTheme();
	}

	@Override
	public void onApplyTheme() {
		super.onApplyTheme();

		Iterator<String> iterator = mTabManager.mTabs.keySet().iterator();
		while (iterator.hasNext()) {
			String key = iterator.next();
			NRFragment fragment = (NRFragment) (mTabManager.mTabs.get(key).fragment);
			if (fragment != null && fragment.isAdded()) {
				fragment.onApplyTheme();
			}
		}
	}

	public static class TabManager implements android.widget.TabHost.OnTabChangeListener,
	android.widget.TabHost.TabContentFactory {
		private final FragmentActivity mActivity;

		private final TabHost mTabHost;

		private final int mContainerId;

		private final LinkedHashMap<String, TabInfo> mTabs = new LinkedHashMap<String, TabInfo>();

		TabInfo mLastTab;

		private final NRTabFragment mNRTabFragment;

		private ViewGroup mContainer;

		public static final class TabInfo {
			final String tag;

			final Class<?> clss;

			final Bundle args;

			Fragment fragment;
			
			final boolean hasView;
			
			public TabInfo(String _tag, Class<?> _class, Bundle _args) {
				this(_tag, _class, _args, true);
			}

			public TabInfo(String _tag, Class<?> _class, Bundle _args,  boolean _hasView) {
				tag = _tag;
				clss = _class;
				args = _args;
				hasView = _hasView;
			}

			public Fragment getFragment() {
				return fragment;
			}
			
			public Bundle getArgs() {
                return args;
            }
		}

		static class DummyTabFactory implements TabHost.TabContentFactory {
			private final Context mContext;

			public DummyTabFactory(Context context) {
				mContext = context;
			}

			@Override
			public View createTabContent(String tag) {
				View v = new View(mContext);
				v.setMinimumWidth(0);
				v.setMinimumHeight(0);
				return v;
			}
		}

		private TabManager(FragmentActivity activity,
				NRTabFragment nrTabFragment, TabHost tabHost, int containerId, boolean needListener) {
			mActivity = activity;
			mTabHost = tabHost;
			mContainerId = containerId;
            if (needListener) {
                mTabHost.setOnTabChangedListener(this);
            }
			mNRTabFragment = nrTabFragment;
			mContainer = (ViewGroup) nrTabFragment.getView().findViewById(
					containerId);
		}

		public LinkedHashMap<String, TabInfo> getTabInfos() {
			return mTabs;
		}

		public TabInfo getTabInfo(String tag) {
			return mTabs.get(tag);
		}

		public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) {
			String tag = tabSpec.getTag();
			TabInfo info = new TabInfo(tag, clss, args);
			addTab(tabSpec, info);
		}

		public void addTab(TabHost.TabSpec tabSpec, TabInfo info) {
		    if (mNRTabFragment.isAllDummyView()) {
		        tabSpec.setContent(new DummyTabFactory(mActivity));
		    } else if (info.hasView) {
				tabSpec.setContent(this);
			} else {
				tabSpec.setContent(new DummyTabFactory(mActivity));
			}
			
			String tag = tabSpec.getTag();

			// Check to see if we already have a fragment for this tab, probably
			// from a previously saved state. If so, deactivate it, because our
			// initial state is that a tab isn't shown.
			FragmentManager fm = mActivity.getSupportFragmentManager();
			info.fragment = fm.findFragmentByTag(tag);
			if (info.fragment != null && !info.fragment.isDetached()) {
				FragmentTransaction ft = fm.beginTransaction();
				ft.detach(info.fragment);
				FragmentUtil.commitAndExec(fm, ft, false);
			}
			mTabs.put(tag, info);
			mTabHost.addTab(tabSpec);
		}

	
		// 以下方法切换tab时使用默认实现
		@Override
		public void onTabChanged(String tabId) {
			TabInfo newTab = mTabs.get(tabId);
			if (mLastTab != newTab) {
				if (mLastTab != null) {
					((NRFragment) mLastTab.fragment).unSelectInTab();
				}
				
                if (!newTab.hasView) {
                    if (newTab.fragment == null) {
                        newTab.fragment = mNRTabFragment.addFragmentByTag(0, newTab.clss,
                                newTab.tag, newTab.args);
                    } else if (newTab.fragment.isDetached()) {
                        FragmentManager fm = mNRTabFragment.getFragmentManager();
                        FragmentTransaction ft = fm.beginTransaction();
                        ft.attach(newTab.fragment);
                        FragmentUtil.commitAndExec(fm, ft, false);
                    }

                }
				
				((NRFragment) newTab.fragment).selectInTab();
				mLastTab = newTab;
				
				if (((NRFragment) newTab.fragment).mParent == null) {
				    ((NRFragment) newTab.fragment).mParent = mNRTabFragment;
				}
				
				mNRTabFragment.onTabChanged(tabId);
			}
		}

		@Override
		public View createTabContent(String tag) {
			TabInfo newTab = mTabs.get(tag);
			newTab.fragment = mNRTabFragment.addFragmentByTag(0,
					newTab.clss, newTab.tag, newTab.args);
			if (newTab.fragment instanceof NRTabFragment) {
				((NRTabFragment) newTab.fragment).setup();
			}
			return newTab.fragment.getView();
		}
	}
}
